﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Routing;
using elfam.web.Controllers;
using elfam.web.Dao;
using elfam.web.Models;
using NHibernate;
using NHibernate.Criterion;

namespace elfam.web.Paging
{
    public class TableModel<T>
    {
        public SearchCriteria SearchCriteria { get; set; }
        public IList<T> Models { get; set; }
        public int Total { get; set; }

        private const int PageSize = 20;
        // todo 
        private static DaoTemplate daoTemplate = new DaoTemplate();
        private string listActionUrl;

        public static TableModel<T> Build(SearchCriteria request, string listActionUrl)
        {
            

            TableModel<T> model = new TableModel<T>();
            model.SearchCriteria = request;
            model.listActionUrl = listActionUrl;

            int start = (request.PageIndexDefault() - 1) * PageSize;
            IList<T> models = daoTemplate.FindByCriteria<T>(request.Criteria, start, PageSize);
            model.Models = models;

            DetachedCriteria countCriteria = CriteriaTransformer.TransformToRowCount(request.Criteria);
            int total = countCriteria.GetExecutableCriteria(daoTemplate.Session).UniqueResult<int>();
            model.Total = total;

            return model;
        }

        public int TotalPages()
        {
            return (int)Math.Ceiling((double)Total / PageSize);
        }

        public string Pager()
        {
            return Extensions.Extensions.PageLinks(new PagingInfo()
                                                       {
                                                           CurrentPage = SearchCriteria.PageIndexDefault(),
                                                           TotalPages = TotalPages()
                                                       }, i => GenerateLink(SearchCriteria, i));
        }

        


        public string Header(string caption, string sortExpression)
        {
            SearchCriteria anotherRequest = new SearchCriteria();
            anotherRequest.Criteria = SearchCriteria.Criteria;
            anotherRequest.PageIndex = SearchCriteria.PageIndex;
            if (sortExpression.Equals(SearchCriteria.SortFieldDefault()))
            {
                if (SearchCriteria.SortDirectionDefault().Equals(SearchCriteria.AscSearchOrder))
                    anotherRequest.SortDirection = SearchCriteria.DescSearchOrder;
                else
                    anotherRequest.SortDirection = SearchCriteria.AscSearchOrder;
            }
            else
                anotherRequest.SortDirection = SearchCriteria.AscSearchOrder;
            anotherRequest.SortExpression = sortExpression;
            anotherRequest.SearchParams.AddRange(SearchCriteria.SearchParams);
            string highlited = "";
            if (sortExpression.Equals(SearchCriteria.SortFieldDefault()))
                highlited = " class=\"sort-highlight\" ";
            return string.Format("<a {2} href=\"{0}\">{1}</a>", GenerateLink(anotherRequest, SearchCriteria.PageIndexDefault()), caption, highlited);
        }

        public string Link(SearchCriteria criteria)
        {
            PropertyInfo[] propertyInfos = criteria.GetType().GetProperties();
            var nameValues = new List<NameValue>();
            foreach (PropertyInfo propertyInfo in propertyInfos)
            {
                if (propertyInfo.GetCustomAttributes(typeof(LinkAttribute), false).Length > 0)
                    nameValues.Add(new NameValue(propertyInfo.Name, propertyInfo.GetValue(criteria, null).ToString()));
            }
            string queryString = string.Join("&", nameValues.Select(x => x.ToString()).ToArray());
            return listActionUrl + "?" + queryString;
        }

        public string HeaderReflection(string caption, string sortExpression)
        {
            SearchCriteria anotherSc;
            if (sortExpression == SearchCriteria.SortExpression)
            {
                if (SearchCriteria.SortDirectionDefault().Equals(SearchCriteria.AscSearchOrder))
                    anotherSc = SearchCriteria.Desc();
                else
                    anotherSc = SearchCriteria.Asc();
            }
            else
               anotherSc = SearchCriteria.OrderBy(sortExpression);
            
            string highlited = "";
            if (sortExpression.Equals(SearchCriteria.SortFieldDefault()))
                highlited = " class=\"sort-highlight\" ";
            return string.Format("<a {2} href=\"{0}\">{1}</a>", Link(anotherSc), caption, highlited);
        }

        public string GenerateLink(object paramValues)
        {
            RouteValueDictionary routeValueDictionary = new RouteValueDictionary(paramValues);
            var nameValues = new List<NameValue>();
            foreach (KeyValuePair<string, object> pair in routeValueDictionary)
            {
                nameValues.Add(new NameValue(pair.Key, pair.Value.ToString()));
            }
            string queryString = string.Join("&", nameValues.Select(x => x.ToString()).ToArray());
            return listActionUrl + "?" + queryString;
        }

        public string GenerateLink(SearchCriteria request, int pageIndex)
        {
            var nameValues = new List<NameValue>();
            nameValues.Add(new NameValue(SearchCriteria.PageIndexProperty, pageIndex.ToString()));
            nameValues.Add(new NameValue(SearchCriteria.SortFieldProperty, request.SortFieldDefault()));
            nameValues.Add(new NameValue(SearchCriteria.SortDirectionProperty, request.SortDirectionDefault()));
            nameValues.AddRange(request.SearchParams);
            string queryString = string.Join("&", nameValues.Select(x => x.ToString()).ToArray());
            return listActionUrl + "?" + queryString;
        }
    }
}
